/*
 * Create Date 2006-5-19
 */
package com.jmcgg.freesky.common.db;

import java.io.Serializable;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.log4j.Logger;

/**
 * Title: FreeSky Common Java Library <br>
 * Description: FreeSky Common Java Library <br>
 * Copyright: Copyright (c) 2005~2009 www.afss.cn <br>
 * Company: Amei's FreeSky Studio <br>
 * 
 * @author <b>Jacky Chou</b> (AFSS [Amei's FreeSky Studio])
 * @version 1.2.1, 2008-08-05, Clean and optimize the source code. <br>
 *          1.2.0, 2008-02-23, Upgrade freesky.jar to 1.2.0 with Struts 2 <br>
 *          1.0.0, 2006-05-30, Initial Version
 */
public abstract class DBConnBean implements Serializable, IDBConn {
	private static final long serialVersionUID = 7187870319928557682L;

	/**
	 * Log4J Logger for this class
	 */
	static final Logger logger = Logger.getLogger(DBConnBean.class);

	protected Connection conn = null;
	protected Statement stmt = null;
	// ������Ԫ������
	private boolean unitOfWork = false;

	public DBConnBean() {
		getConnection();
	}

	public static DBConnBean instance(String db) {
		DBConnBean bean = null;
		if (db.equalsIgnoreCase("Access")) {
			bean = new DBAccessBean();
		} else if (db.equalsIgnoreCase("Oracle")) {
			bean = new DBOracleBean();
		} else if (db.equalsIgnoreCase("DB2")) {
			bean = new DBDb2Bean();
		} else if (db.equalsIgnoreCase("MySQL")) {
			bean = new DBMySQLBean();
		} else if (db.equalsIgnoreCase("SqlServer2k")) {
			bean = new DBSql2kBean();
		} else if (db.equalsIgnoreCase("SqlServer2k5")) {
			bean = new DBSql2k5Bean();
		} else
			bean = new DBAccessBean();
		return bean;
	}

	public abstract void getConnection();

	/**
	 * ����һ������conn
	 * 
	 * @return conn is a Connection to database
	 */
	public Connection getDBConnection() {
		if (conn == null) {
			logger.error("ȡ������ʧ�ܣ�ConnectDB.getDBConnection()");
		}
		return conn;
	}

	/**
	 * ��ݲ�ѯ���sqlstr��ѯ��ݿ�
	 * 
	 * @param sqlStr
	 * @return ResultSet
	 */
	public ResultSet executeQuery(String sqlStr) throws SQLException {
		ResultSet rs = null;

		// �������Ϊnull�����½�����
		if (conn == null) {
			getConnection();
		}
		try {
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sqlStr);
			return rs;
		} catch (SQLException e) {
			logger.error("ִ�в�ѯ���ʧ��ConnectDB.executeQuery: ".concat(e
					.getMessage()));
			logger.error("��ѯʧ�����Ϊ��" + sqlStr);
			throw e;
		}
	}

	/**
	 * ����prepareStatement��Ϊ���������������������sql����еĲ�����������
	 * 
	 * @param sqlStr
	 * @return pstmt PreparedStatement
	 * @throws SQLException
	 */
	public PreparedStatement prepareStatement(String sqlStr)
			throws SQLException {
		PreparedStatement pstmt = null;
		// �������Ϊnull��ֱ�ӷ��أ������½����ӣ���Ϊ��������ֻ����ͬһ����
		if (conn == null) {
			return pstmt;
		}
		pstmt = conn.prepareStatement(sqlStr);
		return pstmt;
	}

	/**
	 * ������sqlStr������ݿ�
	 * 
	 * @param sqlStr
	 *            ������ݿ��SQL���
	 * @return ������ݿ�Ӱ�������
	 * @throws SQLException
	 *             ����ʧ�ܵ��쳣
	 */
	public int executeUpdate(String sqlStr) throws SQLException {
		// �������Ϊnull��ֱ�ӷ���false�����½����ӣ���Ϊ�п������������õ��˷���
		// �������б�����ͬһ������ʵ��
		/*
		 * if (conn == null) { Helper.log().error("sqlexecuteUpdate: no
		 * Connection is active!"); return false; }
		 */
		// ԭ�ȵ�commit()�����ŵ�����ִ�У�����Ϳ����������жԴ˷������е���
		int resultNum; // ������ݿ�Ӱ�������
		try {
			stmt = conn.createStatement();
			resultNum = stmt.executeUpdate(sqlStr);
			stmt.close();
			return resultNum;
		} catch (SQLException ex) {
			logger.error("ִ�и������ʧ��ConnectDB.executeUpdate: ".concat(ex
					.getMessage()));
			logger.error("����ʧ�����Ϊ��" + sqlStr);
			throw ex;
		}
		// return false;
	}

	/**
	 * ��־��ʼ����
	 * 
	 * @param supportTran
	 *            If supportTran is true, it is a Transaction. And
	 *            setAutoCommit(false). If supportTran is false, it is NOT a
	 *            Transaction. And setAutoCommit(true).
	 * @throws SQLException
	 */
	public void beginTran(boolean supportTran) throws SQLException {
		// �Ƿ�����Ԫ��������֧������
		unitOfWork = supportTran;
		try {
			if (supportTran) {
				// ֧�����񣬼����������?��setAutoCommit��Ϊfalse���ĳ��ֶ��ύ
				conn.setAutoCommit(false);
			} else {
				// �������񣬸��º��Զ��ύ
				conn.setAutoCommit(true);
			}
		} catch (SQLException e) {
			logger.error("beginTran(boolean)", e);
			logger.error("��ʼ�������ʧ��ConnectDB.beginTran:".concat(e
					.getMessage()));
			throw e;
		}
	}

	/**
	 * ����ύ����
	 * 
	 * @throws SQLException
	 */
	public void commitTran() throws SQLException {
		// �ж��Ƿ���һ����
		if (unitOfWork) {
			try {
				// �����ύ
				conn.commit();
			} catch (SQLException e) {
				// �ύʧ�ܣ�ROLLBACK
				rollBackTran();
				logger.error("�����ύʧ��ConnectDB.commitTran:".concat(e
						.getMessage()));
				throw e;
			}
		}
		close();
	}

	/**
	 * rollBack
	 * 
	 * @return
	 * @throws SQLException
	 */
	public boolean rollBackTran() throws SQLException {
		try {
			conn.rollback();
			close();
			return true;
		} catch (SQLException e) {
			logger.error("����ع�ʧ��ConnectDB.rollBackTran:".concat(e
					.getMessage()));
			throw e;
		}
		// return false;
	}

	/**
	 * �ر�����
	 */
	public void close() {
		try {
			if (conn != null && !conn.isClosed()) {
				conn.close();
			}
		} catch (SQLException e) {
			logger.error("�ر�����ʧ��ConnectDB.close:".concat(e.getMessage()));
		}
	}

	/**
	 * close ResultSet
	 * 
	 * @param rs
	 */
	public void closeResultSet(ResultSet rs) {
		try {
			if (rs != null) {
				rs.close();
			}
		} catch (SQLException e) {
			logger.error("�رղ�ѯ���ʧ��ConnectDB.closeResultSet:".concat(e
					.getMessage()));
		}
	}

	/**
	 * close Statement
	 * 
	 * @param st
	 */
	public void closeStatement() {
		try {
			if (stmt != null) {
				stmt.close();
			}
		} catch (SQLException e) {
			logger.error("�ر�״̬���ʧ��ConnectDB.closeStatement:".concat(e
					.getMessage()));
		}
	}

	/**
	 * �õ�һ������ܹ���¼��
	 * 
	 * @param sql
	 *            String
	 * @return int
	 */
	public int getTotal(String sql) {
		int ret = 0;
		if (sql == null) {
			return ret;
		}
		ResultSet rs = null;
		try {
			rs = this.executeQuery(sql);
			if (rs.next()) {
				ret = rs.getInt(1);
			}
			rs.close();
		} catch (SQLException sqle) {
			logger.error("getTotal(String sql)".concat(sqle.getMessage()));
			if (rs != null) {
				this.closeResultSet(rs);
			}
		}
		return ret;
	}
}
